/*******************************************************************************
 * Copyright (c) 2010, 2010 Xbeam Project and ChenZhiKong.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 *******************************************************************************/
package org.bellusoft.xbeam.framework.resolve;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 *Default implementation of {@link Resolver}.
 *
 *<p>This resolver can be customized by setting {@link ModuleMatcher module matcher}, 
 *{@link PackageMatcher package matcher}, {@link Comparator module priority comparator},
 *{@link Comparator package priority comparator} and {@link ResolverDebug debug} in the constructor.
 *
 *<p>
 *<strong>Contract:</strong>
 *<ol>
 *<li>Thread Safe</li>
 *</ol>
 *  
 *@see ModuleMatcher
 *@see PackageMatcher 
 */
public class ResolverImp {
	
	final ModuleMatcher moduleMatcher ; 
	
	final PackageMatcher packageMatcher ; 
	
	final Comparator<ModuleResolveData> modulePriorityComparator ; 
	
	final Comparator<ExportPackage> packagePriorityComparator ; 
	
	final ResolveContext resolveContext ; 
	
	private final ResolverDebug debug ; 
	
	private final Lock lock = new ReentrantLock();  
	
	/**
	 *<p>
	 *<strong>Contract:</strong>
	 *<ol>
	 *<li>Parameter moduleMatcher must not be <code>null</code>.</li>
	 *<li>Parameter packageMatcher must not be <code>null</code>.</li>
	 *<li>Parameter modulePriorityComparator must not be <code>null</code>.</li>
	 *<li>Parameter packagePriorityComparator must not be <code>null</code>.</li>
	 *</ol> 
	 *
	 * @param moduleMatcher Module matcher.
	 * @param packageMatcher Package matcher.
	 * @param modulePriorityComparator Module Priority comparator.
	 * @param packagePriorityComparator Package Priority comparator.
	 * @param debug Resolver debug.
	 */
	public ResolverImp(ModuleMatcher moduleMatcher, PackageMatcher packageMatcher, 
			Comparator<ModuleResolveData> modulePriorityComparator, Comparator<ExportPackage> packagePriorityComparator, ResolverDebug debug) {
		if(moduleMatcher==null){
			throw new IllegalArgumentException("The param moduleMatcher can not be null.");
		}
		if(packageMatcher==null){
			throw new IllegalArgumentException("The param packageMatcher can not be null.");
		}
		if(modulePriorityComparator==null){
			throw new IllegalArgumentException("The param modulePriorityComparator can not be null.");
		}
		if(packagePriorityComparator==null){
			throw new IllegalArgumentException("The param packagePriorityComparator can not be null.");
		}
		this.moduleMatcher = moduleMatcher ; 
		this.packageMatcher = packageMatcher ;
		this.modulePriorityComparator = modulePriorityComparator ; 
		this.packagePriorityComparator = packagePriorityComparator ; 
		this.debug = debug ; 
		this.resolveContext = new ResolveContext(); 
	}
	
	public Map<ModuleResolveData,ModuleResolveResult> resolve(List<ModuleResolveData> resolveDatas){
		lock.lock() ; 
		try{
			ResolveProcess process = new ResolveProcess(this, resolveDatas);
			return process.run() ; 
		}finally{
			lock.unlock();
		}
	}
	
	public ModuleResolveResult resolve(ModuleResolveData resolveData){
		lock.lock() ; 
		try{
			return resolve(Arrays.asList(resolveData)).get(resolveData) ; 
		}finally{
			lock.unlock();
		}
	}
	
	public void confirmResolved(ModuleResolveData resolvedData){
		lock.lock() ; 
		try{
			
		}finally{
			lock.unlock();
		}
		
	}
	
	public boolean unresolve(ModuleResolveData resolveData){
		lock.lock() ; 
		try{
			return false ; 
		}finally{
			lock.unlock();
		}
	}
	
	/**
	 *Record resolving debug information.
	 * 
	 * @param message debug information
	 */
	void debug(String message){
		if(debug!=null){
			debug.resolverDebug(message);
		}
	}
	
}
